#include <sstream>
#include <list>
#include <stdio.h>
#include <string.h>
#include "Trace.h"

#ifndef __ANDROID__
#	define TRACE_FONT "Font\\trace.ttf"
#else
#	define TRACE_FONT "./Font/trace.ttf"
#endif

Trace trace;

Trace::Trace()
{
}

Trace::~Trace()
{
}

void Trace::Setk(int x, int y, int w, int h)
{
	if (this->Font != (decltype(this->Font))0)
		FreeFontHandle(this->Font);
	this->Font = CreateFontHandle(TRACE_FONT, 16);
	TestTextSize(this->Font, " ", &this->FontWidth, &this->FontHeight);

	this->Field.x = x; this->Field.y = y;
	this->Field.w = w; this->Field.h = h;
	this->CharNumPerLine = this->Field.w / this->FontWidth;
	sprintf(this->parse_fmt, "%%%d[^\n]s", this->CharNumPerLine);
	this->LineNumPerPage = this->Field.h / this->FontHeight;

	if (this->Background != nullptr)
		FreeSurface(this->Background);
	this->Background = CreateSurface(this->Field.w, this->Field.h);
	FillRect(this->Background, nullptr, this->BackgroundColor);

	if (this->BufferSurface != nullptr)
		FreeSurface(this->BufferSurface);
	this->BufferSurface = CreateSurface(this->Field.w, this->Field.h);
	BlitSurface(this->Background, nullptr, this->BufferSurface, nullptr);
}

void Trace::DrawText(const char *AppendText)
{
	// check font
	if (this->Font == (decltype(this->Font))0)
		throw "Fail to load font file.";

	// draw background
	BlitSurface(this->Background, nullptr, this->BufferSurface, nullptr);

	// cut string to multi-line
	char *ptr = (char*)AppendText, *buf;
	for (int i = 0; *ptr != '\0'; i++)
	{
		buf = (char*)malloc(this->CharNumPerLine + 1);
		sscanf(ptr, this->parse_fmt, buf);
		this->TraceText.push_back(buf);
		ptr += strlen(buf);
		ptr += (*ptr == '\n')? 1 : 0;
	}
	while (this->TraceText.size() > this->LineNumPerPage)
	{
		free(this->TraceText.front());
		this->TraceText.pop_front();
	}

	// draw frontground
	int index = 0;
	for (auto text = this->TraceText.begin(); text != this->TraceText.end(); text++, index++)
	{
		char *tmp = *text;
		Surface fsur = RenderText(this->Font, tmp, 0xFFFFFF);

		SFC_Rect TRect = {0, 0 + index * this->FontHeight, fsur->w, fsur->h};
		BlitSurface(fsur, nullptr, this->BufferSurface, &TRect);

		FreeSurface(fsur);
	}
}

void Trace::Show(Surface surface)
{
	std::string buf = (*this).str();
	if (buf.length() > 0) {
		char tmp[32];
		sprintf(tmp, "[%d]", this->DisplayCount++);
		buf.insert(0, tmp);
		DrawText(buf.c_str());
		(*this).str("");
	}
	BlitSurface(this->BufferSurface, nullptr, surface, &this->Field);
}